﻿/**
    测试javascript中this的功能，关启强
    总的来说，如果是普通对象的this，则表示拥有该对象的类。
    如果是方法的this，则表示该方法的base
*/

//1、由于括号()左边的匿名函数是非引用类型对象（它既不是标识符也不属于属性访问），
//因此，this的值设置为全局对象。
(function () {

    this.writeln = function (msg) {
        if (msg == undefined) {
            $("#info").append("<p></p>");
            return;
        }
        $("#info").append(msg + "<br />");
    };

    this.testthis = function () {
        //好好研究下foo.say和person.say
        foo.say = person.say;
        //my name is gqq
//        foo.say();
        //my name is another
//        person.say();

        //后面三个发生了一次赋值现象，调用了GetValue方法。返回的是一个函数对象。
        //而不是引用foo，意味着this的值被设置成null。
//        foo.bar();//foo
//        (foo.bar)();//foo
//        (foo.bar = foo.bar)();//window
//        (false || foo.bar)();//window
//        (foo.bar, foo.bar)();//window
        //本质上类似于
        var winbar = foo.bar;
//        winbar();

        //在这个方法中，innerfun的base是foo，但是innerfun中f的base是活跃对象（activation object）。
        //foo.innerfun();

        //测试构造函数。、
        //
        //函数作为构造函数时，我们通过new操作符创建实例对象是，
        //它会调用Foo()函数的内部[[Construct]]方法；
        //在对象创建之后，会调用内部的[[Call]]方法，然后所有Foo()函数中this的值会设置为新创建的对象。
        var foocon = new FooCons();
        writeln("get foocons from contructor...");
        writeln(foocon);
        writeln(foocon.age);
        writeln(foocon.name);
        writeln();
        var callobj = {};
        FooCons.call(callobj, "p1", "p2");

        writeln("obj callobj....");
        writeln(callobj.p1);
        writeln(callobj.p2);
        writeln();
        var appobj = {};
        FooCons.apply(appobj, ["arr1", "arr2"]);

        writeln("obj appobj....");
        writeln(appobj.p1);
        writeln(appobj.p2);
        writeln();
        //        var usecons = FooCons.constructor.call();
//        alert(usecons.name);
        

        var test1 = foo.base;
        var test2 = foo.propertyName;
    };


})();

var info = "gqq this test";

/*
*   如果直接调用，this表示为window对象，它有一个方法叫做fooCoder()
*/
function fooCoder(x) {
    this.x = x;
    //    alert(this.info);
}

/*
*   如果推测不错，调用fooCoder之后再调用testthisfromfoocoder
    window对象中多了一个x属性。
    因此，前面的fooCoder方法我们可以认为是window的一个方法。
    而这个方法就给window对象新加了一个属性。
*/
function testthisfromfoocoder() {
    //    alert(this.x);
}

var foo = {
    name: "gqq",
    bar: function() {
        alert(this);
    },
    innerfun: function() {

        function f() {
            alert(this);
        }

        f();
    }
};

var person = {
    name: "another",
    say: function () {
        alert(this === person);
        //不能对this进行赋值。
        //this = foo;
        alert("my name is " + this.name);
    }
};

function FooCons(param1,param2) {
    //alert(this);
    this.name = "gqq";
    this.age = 30;
    this.p1 = param1;
    this.p2 = param2;
}

// Declares anonymous function
(function () {
    //alert(this); // null => global
})();
